#pragma once

#include "./macro.h"
#include <iostream>
#include <string>
#include <mutex>
#include <chrono>
#include <ctime>
#include <cstdarg>
#include <algorithm>
#include <thread>
#include <future>

#include "../threadpool/tp_define.h"

namespace burn {

class UTimer {
public:
  UTimer() = default;
  ~UTimer() { stop(); }

  /**
   * 开始执行定时器
   * @param interval 间隔时间，单位ms
   * @param task
   */
  template <typename FunctionType>
  CVoid start(CMSec interval, const FunctionType &task) {
    if (!is_stop_) {
      return; // 如果正在执行中，则无法继续执行
    }

    is_stop_ = false;
    /**
     * std::launch::async：在调用async就开始创建线程。
     * std::launch::deferred：延迟加载方式创建线程。调用async时不创建线程，直到调用了future的get或者wait时才创建线程。
     * 后期会考虑将这个功能融合到线程池中去
     */
    future_ = std::async(std::launch::async, [this, interval, task]() {
      while (!is_stop_) {
        CGRAPH_UNIQUE_LOCK lk(mutex_);
        const auto &result =
            cv_.wait_for(lk, std::chrono::milliseconds(interval));
        if (std::cv_status::timeout == result) {
          task();
        }
      }
    });
  }

  /**
   * 关闭定时器
   */
  CVoid stop() {
    if (is_stop_) {
      return;
    }

    is_stop_ = true;
    cv_.notify_one();
    future_.wait();
  }

private:
  std::atomic<CBool> is_stop_{true};
  std::mutex mutex_;
  std::condition_variable cv_;
  std::future<CVoid> future_{};
};

} // namespace burn